using System.Runtime.InteropServices;

namespace FinMkts.Messaging.Pgm
{
    [StructLayout(LayoutKind.Sequential)]
    public class RmSenderStats
    {
        // this might look odd as there is no way of setting these fields
        // but the fields are set by the marhsalling code when we get the data from the socket
        private ulong _dataBytesSent;
        private ulong _totalBytesSent;
        private ulong _naksReceived;
        private ulong _naksReceivedTooLate; 
        private ulong _outstandingNaks;
        private ulong _naksAfterRData;
        private ulong _repairPacketsSent;
        private ulong _bufferSpaceAvailable; 
        private ulong _trailingEdgeSeqId;
        private ulong _leadingEdgeSeqId;
        private ulong _rateKBitsPerSecOverall;
        private ulong _rateKBitsPerSecLast;
        private ulong _totalODataPacketsSent;

        /// <summary>
        /// # client data bytes sent out so far
        /// </summary>
        public BinarySize ClientDataSent
        {
            get { return BinarySize.FromBytes(_dataBytesSent); }
        }

        /// <summary>
        /// SPM, OData and RData bytes
        /// </summary>
        public BinarySize TotalDataSent
        {
            get { return BinarySize.FromBytes(_totalBytesSent); }
        }

        /// <summary>
        /// amount of free space in the buffer
        /// </summary>
        public BinarySize BufferSpaceAvailable
        {
            get { return BinarySize.FromBytes(_bufferSpaceAvailable); }
        }

        /// <summary>
        /// Internally calculated send-rate from the beginning
        /// </summary>
        public BinarySize RatePerSecOverall
        {
            get { return BinarySize.FromKiloBits(_rateKBitsPerSecOverall); }
        }

        /// <summary>
        /// Send-rate calculated every INTERNAL_RATE_CALCULATION_FREQUENCY
        /// </summary>
        public BinarySize RatePerSecLast
        {
            get { return BinarySize.FromKiloBits(_rateKBitsPerSecLast); }
        }

        /// <summary>
        /// # NAKs received so far
        /// </summary>
        public ulong NaksReceived
        {
            get { return _naksReceived; }
        }

        /// <summary>
        /// # NAKs recvd after window advanced
        /// </summary>
        public ulong NaksReceivedTooLate
        {
            get { return _naksReceivedTooLate; }
        }

        /// <summary>
        /// # NAKs yet to be responded to
        /// </summary>
        public ulong OutstandingNaks
        {
            get { return _outstandingNaks; }
        }

        /// <summary>
        /// # NAKs yet to be responded to
        /// </summary>
        public ulong NaksAfterRData
        {
            get { return _naksAfterRData; }
        }

        /// <summary>
        /// # Repairs (RDATA) sent so far
        /// </summary>
        public ulong RepairPacketsSent
        {
            get { return _repairPacketsSent; }
        }

        /// <summary>
        /// smallest (oldest) Sequence Id in the window
        /// </summary>
        public ulong TrailingEdgeSeqId
        {
            get { return _trailingEdgeSeqId; }
        }

        /// <summary>
        /// largest (newest) Sequence Id in the window
        /// </summary>
        public ulong LeadingEdgeSeqId
        {
            get { return _leadingEdgeSeqId; }
        }

        /// <summary>
        /// Total original data (ODATA) packets sent
        /// </summary>
        public ulong TotalODataPacketsSent
        {
            get { return _totalODataPacketsSent; }
        }

        public override string ToString()
        {
            return string.Format("ClientDataSent: {0}, TotalDataSent: {1}, NaksReceived: {2:N0}, NaksReceivedTooLate: {3:N0}, OutstandingNaks: {4:N0}, NaksAfterRData: {5:N0}, RepairPacketsSent: {6:N0}, BufferSpaceAvailable: {7}, TrailingEdgeSeqId: {8:N0}, LeadingEdgeSeqId: {9:N0}, RatePerSecOverall: {10}, RatePerSecLast: {11}", 
                ClientDataSent, TotalDataSent, 
                _naksReceived, _naksReceivedTooLate, _outstandingNaks, _naksAfterRData, _repairPacketsSent, 
                BufferSpaceAvailable, _trailingEdgeSeqId, _leadingEdgeSeqId,
                RatePerSecOverall.ToString(BitsBytes.Bits), RatePerSecLast.ToString(BitsBytes.Bits));
        }
    }
}